//
// Created on 2025/6/6.
//
// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found,
// please include "napi/native_api.h".

#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <cstring>
#include "udp.h"
//
#include <sys/time.h>
#include "hilog/log.h"

#define MAX_UDP 3

#define PACK_NUM 5

MessageQueue g_queue[MAX_UDP];

int g_socket[MAX_UDP];

int g_port[MAX_UDP];

int g_cfg[MAX_UDP];

int g_thread_run[MAX_UDP];

pthread_t g_thread_id[MAX_UDP];



int find_idle_port(int port)
{
	
	int i = 0;
	
	while(i < MAX_UDP)
	{
		if(g_cfg[i] == 1)
		{
				
				if(g_port[i] == port)
				{
						return -1;
				}
		}
		i++;
					
	}
	
	i = 0;
	
	while(i < MAX_UDP)
	{
		if(g_cfg[i] == 0)
		{
				
				return i;
		}
		
		i++;
	}
	
	return -1;
	
}

int find_pos_for_socket(int socket)
{
	
	int i = 0;
	
	while(i < MAX_UDP)
	{
		//printf("g_cfg[i] = %d g_socket[i] = %d socket = %d\n", g_cfg[i], g_socket[i], socket);
		if(g_cfg[i] == 1)
		{
				
				if(g_socket[i] == socket)
				{
						return i;
				}
		}
		i++;
					
	}
	
	return -1;
	
}



// 发送UDP数据
int send_udp_data(char* ip, int port,  char* data, int data_len) {
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        return -1; // 套接字创建失败
    }

    struct sockaddr_in dest_addr;
    dest_addr.sin_family = AF_INET;
    dest_addr.sin_port = htons(port);
    
    if (inet_pton(AF_INET, ip, &dest_addr.sin_addr) <= 0) {
        close(sockfd);
        return -1; // IP地址无效
    }

    int send_len = sendto(sockfd, data, data_len, 0, 
                          (struct sockaddr*)&dest_addr, sizeof(dest_addr));
    close(sockfd);
    return (send_len == data_len) ? 0 : -1; // 发送成功/失败
}




void * thread_function( void *arg )  
{
    int socket = 0;
    
    socket = *(int *)arg;
    
    char *buf = NULL;
    
    int i = 0;
    
    char msg_buf[20480];
    
    int pos = 4;
    
    int len = 0;
    
    int pos1 = 0;
    
    int num = 0;
    
    OH_LOG_Print(LOG_APP, LOG_DEBUG, 0xff00, "Udp_recv", "thread_function");
    pos1 = find_pos_for_socket(socket);
    
    if(pos1 == -1)
    {
    	printf("socket not find thread_function exit socket is %d\n", socket);
  //      OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "Udp_recv", "socket not find thread_function exit socket is %{publice}", socket);
    	return NULL; 
    }
    
    g_thread_run[pos1] = 1;
    
    while(1){
    		if(g_thread_run[pos1] == 0)
    		{
    				printf("thread exit\n");
    				break;
    		}
    //	printf("recv socket is %d i = %d\n", socket, i);
        buf = recv_udp_data(socket, &len);
   //     printf("len = %d buf = %s\n", len, buf);
   //     OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "Udp_recv", "recv_udp_data len %{publice}", len);
        if(len > 0){
            i++;
            //printf("len = %d buf = %s i = %d socket = %d\n", len, buf,i, socket);
            memcpy(msg_buf + pos , &len, 4);
            
            pos = pos + 4;
            
            memcpy(msg_buf + pos, buf, len);
            
            pos = pos + len;
            
            
            
            //打队列
            if(i == PACK_NUM){
                num++;
               // OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "Udp_recv", "udp recv =%{public}d", num);
                //printf("normal socket %d send queue pos %d pos1 = %d\n", socket, pos,pos1);
                memcpy(msg_buf, &i, 4);
                //OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "Udp_recv", "msg_buf =%{public}x %{public}x %{public}x %{public}x", msg_buf[0],msg_buf[1],msg_buf[2],msg_buf[3]);
                mq_send(&g_queue[pos1], 1, msg_buf, pos);
                
                i = 0;
                
                pos = 4;
            }
            
            delete(buf);
        }
        else
        	{
        		printf("time out\n");
        		
        		if(i > 0)
        			{
        				//int j = 0;
                /*
        				len = 0;
        				while(i < PACK_NUM)
        				{
        						
        						memcpy(msg_buf + pos , &len, 4);
        						
        						pos = pos + 4;
        						
        						i++;
        				}
                */
        				printf("< 5 send\n");
        				
        				//printf("timeout socket %d send queue pos %d\n", socket, pos);
        				num++;
                       // OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "Udp_recv", "udp recv =%{public}d", num);
                        memcpy(msg_buf, &i, 4);
        				mq_send(&g_queue[pos1], 1, msg_buf, pos);
                
        				
        				i = 0;
        				
        				pos = 4;
        			}
        			
        	}
        
        
        
        
    }
    
    
    
    return NULL;  
}


int create_udp(int port)
{
		int pos = 0;
	
		pos = find_idle_port(port);
		
		if(pos == -1)
		{
				
			return -1;
		}
	
	
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    struct sockaddr_in serv_addr;
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(port);
    serv_addr.sin_addr.s_addr = INADDR_ANY;

    if (bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
        close(sockfd);
        return -1;
    }
    
    int new_rcvbuf = 165536; // 新的接收缓存大小，单位为字节
 
    if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &new_rcvbuf, sizeof(new_rcvbuf)) < 0) {
        perror("setsockopt(SO_RCVBUF) failed");
    }
    
    //int reuse = 1;
    //setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
    
    //创建接收线程
    
    pthread_t thread;  
    int ret;  
    //char * arg = "Hello World";
    printf("create socket is %d pos =%d\n", sockfd, pos);
    
    g_socket[pos] = sockfd;
    
    mq_init(&(g_queue[pos]));
    
    g_port[pos] = port;
    
    g_cfg[pos] = 1;
    
    ret = pthread_create(&thread, NULL, thread_function, (void*) &g_socket[pos]);  
    if(ret)  
    {  
        printf("thread create failed\n");  
        return -1;  
    }  
    
    g_thread_id[pos] = thread;
   
   //	printf("thread id = %ld\n", g_thread_id[pos]);
    
    
    
    return sockfd;
}

int close_udp(int socket)
{
		int pos = 0;
		
		
		pos = find_pos_for_socket(socket);
		
		if(pos == -1)
		{
			return -1;
		}
		
		
		
    close(socket);
    
   // pthread_cancel(g_thread_id[pos]);
   
   	g_thread_run[pos] = 0;
    
    g_thread_id[pos] = 0;
    
    
    
    g_cfg[pos] = 0;
    
    
    
    g_socket[pos] = 0;
    
    g_port[pos] = 0;
    
    mq_destroy(&g_queue[pos]);
    
    printf("close udp\n");
    
    return 0;
}




Message* recv_udp_data_queue(int socket)
{
	
	int pos = 0;
	
	pos = find_pos_for_socket(socket);
	
	if(pos == -1)
	{
        //OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "Udp_recv", "recv_udp_data_queue %{public}s %{public}d %{public}d", ip, port, size);
        //OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "Udp_recv", "recv_udp_data_queue socket %{public}d", socket);
		//printf("recv_udp_data_queue find socket =%d error\n", socket);
		return NULL;
	}
	//printf("recv_udp_data_queue socket %d pos is %d\n", socket, pos);
    //OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "Udp_recv", "recv_udp_data_queue socket %{public}d pos %{public}d", socket, pos);
	Message* msg = mq_receive(&g_queue[pos]);
    
	return msg;
    
}

// 接收UDP数据（简化示例，需根据需求优化）
char* recv_udp_data(int socket, int* recv_len) 
{
   
	struct timeval tv;
	int ret;
	tv.tv_sec = 0;
	tv.tv_usec = 100000;
    
    //OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "Udp_recv", "recv_udp_data 1 socket %{public}d", socket);
	if (setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
		
	}
    
    
    char buffer[2048] = {0};
    struct sockaddr_in client_addr;
    socklen_t client_len = sizeof(client_addr);
    *recv_len = recvfrom(socket, buffer, sizeof(buffer), 0, 
                         (struct sockaddr*)&client_addr, &client_len);
    //close(sockfd);
    
   // OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "Udp_recv", "recv_udp_data 2 socket %{public}d", socket);
    if (*recv_len == -1 && errno == EAGAIN)
    	{
		printf("recvfrom timeout\n");
		return nullptr;
	}
    //printf("recv_udp_data 2\n");
   else if (*recv_len > 0) {
        char* result = new char[*recv_len + 1];
        memcpy(result, buffer, *recv_len);
        result[*recv_len] = '\0';
        return result;
    }
    return nullptr;
}



int send_udp(int socket, char *ip, int port,  char* data, int data_len) {
    

    struct sockaddr_in dest_addr;
    dest_addr.sin_family = AF_INET;
    dest_addr.sin_port = htons(port);
    
    if (inet_pton(AF_INET, ip, &dest_addr.sin_addr) <= 0) {
        
        return -1; // IP地址无效
    }

    int send_len = sendto(socket, data, data_len, 0, 
                          (struct sockaddr*)&dest_addr, sizeof(dest_addr));
    
    //OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "send_len", "send_len %{public}d socket %{public}d ip %{public}s port %{public}d", send_len, socket, ip, port);
    
    return (send_len == data_len) ? 0 : -1; // 发送成功/失败
}